package com.fs.realm;

import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTDecodeException;
import com.auth0.jwt.exceptions.JWTVerificationException;
import com.auth0.jwt.interfaces.Claim;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.auth0.jwt.interfaces.JWTVerifier;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.lang.Nullable;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

@Slf4j
public class JwtUtil {

    // 过期时间一小时
    private static final long EXPIRE_TIME = 60 * 60 * 1000 * 2;
    private static final String SECRET = "kfaWhn5i@p797";
    private static final String KEY = "role";

    /**
     * 校验token是否正确
     *
     * @param token TOKEN
     * @return boolean
     */
    public static boolean verify(String token) {
        try {
            Algorithm algorithm = Algorithm.HMAC256(SECRET);
            JWTVerifier verifier = JWT.require(algorithm)
                    .build();
            verifier.verify(token);
            return true;
        } catch (JWTVerificationException e) {
            log.error(e.getMessage());
            return false;
        }
    }


    /**
     * 获取角色
     * @param token 令牌字符串
     * @return role集合
     */
    public static List<String> getRoles(String token){
        DecodedJWT jwt = JWT.decode(token);
        Claim claim = jwt.getClaim(KEY);
        if(claim.isNull()){
            return new ArrayList<String>();
        }

        Pattern pattern = Pattern.compile(",");
        return pattern.splitAsStream(claim.asString()).collect(Collectors.toList());
    }

    /**
     * 无需解密直接获得token中的userId或customerId
     */
    public static @Nullable Integer getPrincipleId(String token) {
        try {
            DecodedJWT jwt = JWT.decode(token);
            List<String> audience = jwt.getAudience();
            if (audience.size() > 0) {
                try {
                    return Integer.parseInt(audience.get(0));
                } catch (NumberFormatException e) {
                    throw new Exception(e.getMessage());
                }
            }
            return null;
        } catch (Exception e) {
            log.error(e.getMessage());
            return null;
        }
    }

    /**
     * 生成签名，并设置过期时间
     *
     * @param userID 用户ID
     * @return token
     */
    public static @Nullable
    String sign(Integer userID, List<String> roles) {
        try {
            Date date = new Date(System.currentTimeMillis() + EXPIRE_TIME);
            Algorithm algorithm = Algorithm.HMAC256(SECRET);
            // 附带username信息
            return JWT.create()
                    .withAudience(userID.toString())
                    .withClaim(KEY, String.join(",", roles))
                    .withExpiresAt(date)
                    .sign(algorithm);
        } catch (Exception e) {
            log.error(e.getMessage());
            return null;
        }
    }
}
